namespace cpputils
{

struct virtual_object
{
	virtual ~virtual_object();
};

class class_factory : private noncopyable
{
public:
	void clear();
	template<class T>
	void add(const string& Name = typeid(T).name())
	{
		add(Name, typeid(T).name(), make_smart_ptr(new object_maker<T>));
	}
	template<class T>
	const string& get_name() const
	{
		return get_name(typeid(T).name());
	}
	const string& get_name(const type_info& TypeInfo) const;
	smart_ptr<virtual_object> make(const string& Name) const;

private:
	struct object_maker_base : public virtual virtual_object
	{
		virtual smart_ptr<virtual_object> make() const = 0;
	};
	template<class T>
	struct object_maker : public object_maker_base
	{
		smart_ptr<virtual_object> make() const
		{
			return make_smart_ptr(new T);
		}
	};

	map<string, smart_ptr<object_maker_base> > NameMakers;
	map<string, string> TypeNames;

	void add(const string& Name, const string& TypeName, smart_ptr<object_maker_base> Maker);
	const string& get_name(const string& TypeName) const;
};

}
